﻿using System.Collections.Generic;
using System.Web.Mvc;
using Moq;
using NUnit.Framework;
using Tamias.BasicCmsPortableArea.Areas.CmsAdmin.Controllers;
using Tamias.BasicCmsPortableArea.Areas.CmsAdmin.ViewModels.ContentGroup;
using Tamias.BasicCmsPortableArea.Domain;

namespace Tamias.UnitTests.ControllerTests
{
    [TestFixture]
    public class ContentGroupControllerTests
    {
        [SetUp]
        public void SetUp()
        {
            _stubService = new Mock<IContentGroupService>();
            _ctrl = new ContentGroupController(_stubService.Object);
        }

        private ContentGroupController _ctrl;
        private Mock<IContentGroupService> _stubService;
        private Mock<IContentItemService> _stubContentItemService;

        [Test]
        public void Index_GroupsExist_ReturnsViewWithGroups()
        {
            _stubService.Setup(svc => svc.GetGroups()).Returns(
                new List<ContentGroup>()
                {
                    new ContentGroup() { Id = 1, Name = "Foo" },
                    new ContentGroup() { Id = 2, Name = "Bar" }
                });

            var result = _ctrl.Index() as ViewResult;
            Assert.IsNotNull(result, "Expected a ViewResult.");

            var vm = result.ViewData.Model as IndexViewModel;
            vm.Groups.Count.IsEqualTo(2, "Expected two groups.");
        }

        [Test]
        public void Index_NoGroupsExist_ReturnsWithNoGroups()
        {
            _stubService.Setup(svc => svc.GetGroups()).Returns(new List<ContentGroup>());
            
            var result = _ctrl.Index() as ViewResult;
            Assert.IsNotNull(result, "Expected a ViewResult.");
            result.ViewName.ToLower().IsEqualTo("nogroups", "Expected the view indicating no groups.");
        }

        [Test]
        public void Create_ReturnsView()
        {
            var result = _ctrl.Create() as ViewResult;
            Assert.IsNotNull(result);
        }

        [Test]
        public void Create_PostingInvalidGroup_ReturnsView()
        {
            _ctrl.ModelState.AddModelError("Name", "Doh!");

            var result = _ctrl.Create(new CreateEditViewModel()) as ViewResult;
            Assert.IsNotNull(result);
        }

        [Test]
        public void Create_PostingValidGroup_ReturnsRedirectToIndex()
        {
            _stubService.Setup(svc => svc.Save(It.IsAny<ContentGroup>()));

            var result = _ctrl.Create(new CreateEditViewModel() { Name = "Foo" }) as RedirectToRouteResult;
            Assert.IsNotNull(result, "Expected a RedirectToRouteResult.");
            result.RouteValues["action"].ToString().ToLower().IsEqualTo("index", "Expected a redirect back to the index page.");
        }

        [Test]
        public void Edit_ContentGroupExists_ReturnsView()
        {
            const int id = 8098;
            const string name = "Foo";
            _stubService.Setup(svc => svc.Get(id)).Returns(new ContentGroup() { Id = id, Name = name });

            var result = _ctrl.Edit(id) as ViewResult;
            Assert.IsNotNull(result, "Expected a ViewResult.");

            var vm = result.ViewData.Model as CreateEditViewModel;
            Assert.IsNotNull(vm, "Expected a CreateEditViewModel");
            vm.Name.IsEqualTo(name, "The name was not returned correctly.");
            vm.ContentGroupId.IsEqualTo(id, "The id was not returned correctly.");
        }

        [Test]
        public void Edit_ContentGroupDoesNotExist_RedirectsToIndex()
        {
            const int id = 45678;
            _stubService.Setup(svc => svc.Get(id));

            var result = _ctrl.Edit(id) as RedirectToRouteResult;
            Assert.IsNotNull(result, "Expected a RedirectToRouteResult");
            result.RouteValues["action"].ToString().ToLower().IsEqualTo("index", "Expected to be redirected to the index page.");
        }

        [Test]
        public void Edit_ContentIdIsInvalid_RedirectsToIndex()
        {
            int? id = null;
            var result = _ctrl.Edit(id) as RedirectToRouteResult;
            Assert.IsNotNull(result, "Expected a RedirectToRouteResult");
            result.RouteValues["action"].ToString().ToLower().IsEqualTo("index", "Expected to be redirected to the index page.");
        }

        [Test]
        public void Edit_PostingInvalidGroup_ReturnsView()
        {
            _ctrl.ModelState.AddModelError("Name", "Doh!");

            var result = _ctrl.Edit(new CreateEditViewModel()) as ViewResult;
            Assert.IsNotNull(result);
        }

        [Test]
        public void Edit_PostingValidGroup_RedirectsToIndex()
        {
            _stubService.Setup(svc => svc.Save(It.IsAny<ContentGroup>()));

            var result = _ctrl.Edit(new CreateEditViewModel() { ContentGroupId = 8, Name = "Foo" }) as RedirectToRouteResult;
            Assert.IsNotNull(result, "Expected a RedirectToRouteResult.");
            result.RouteValues["action"].ToString().ToLower().IsEqualTo("index", "Expected a redirect back to the index page.");
        }

        [Test]
        public void Delete_InvalidId_RedirectsToErrorDeleting()
        {
            int? id = null;
            var result = _ctrl.Delete(id) as RedirectToRouteResult;

            Assert.IsNotNull(result, "Expected a RedirectToRouteResult.");
            result.RouteValues["action"].ToString().ToLower().IsEqualTo("errordeleting", "Expected to be redirected to the ErrorDeleting view.");
        }

        [Test]
        public void Delete_ValidId_RedirectsToIndex()
        {
            int? id = 6;
            _stubService.Setup(svc => svc.Delete(id.Value));

            var result = _ctrl.Delete(id) as RedirectToRouteResult;

            Assert.IsNotNull(result, "Expected a RedirectToRouteResult.");
            result.RouteValues["action"].ToString().ToLower().IsEqualTo("index", "Expected to be redirected to the Index view.");
        }
    }
}
